package com.wht.sip.core.transmit.message;

import cn.hutool.core.util.NumberUtil;
import com.wht.sip.config.SipConfig;
import com.wht.sip.core.Enum.CatalogEvent;
import com.wht.sip.core.Enum.CmdType;
import com.wht.sip.core.context.SipProcessorContext;
import com.wht.sip.core.transmit.model.Device;
import com.wht.sip.core.transmit.model.DeviceAlarm;
import com.wht.sip.core.transmit.model.DeviceChannel;
import com.wht.sip.utils.SipUtils;
import com.wht.sip.utils.XmlUtil;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Element;
import org.noear.solon.annotation.Init;
import org.noear.solon.annotation.Inject;
import org.noear.solon.annotation.Managed;

import javax.sip.RequestEvent;
import javax.sip.header.FromHeader;
import javax.sip.message.Response;
import java.util.Iterator;

/**
 * NOTIFY消息处理
 * @author by HaiTao.Wang on 2025/9/19.
 */
@Slf4j
@Managed
public class NotifyMessageProcessor extends SipRequestProcessorHandle implements SipMessageProcessor {

    @Inject
    SipConfig sipConfig;

    @Init
    public void init() {
        SipProcessorContext.requestProcessor.put("NOTIFY", this);
    }

    /**
     * 处理NOTIFY请求
     *
     * @param event 请求事件
     */
    @SneakyThrows
    @Override
    public void processRequest(RequestEvent event) {

        log.info("收到NOTIFY请求");

        response((SIPRequest) event.getRequest(), Response.OK);
        Element rootElement = getRootElement(event, "gb2312");
        if (rootElement == null) {
            log.error("处理NOTIFY消息时未获取到消息体,{}", event.getRequest());
            response((SIPRequest) event.getRequest(), Response.OK);
            return;
        }

        String cmd = XmlUtil.getText(rootElement, "CmdType");


        if (CmdType.CATALOG.getValue().equals(cmd)) {
            log.info("收到目录消息");
            processNotifyCatalog(event);
        }

        if (CmdType.ALARM.getValue().equals( cmd)) {
            log.info("收到报警消息");
            processNotifyAlarm(event);
        }

        if (CmdType.MOBILE_POSITION.getValue().equals( cmd)) {
            log.info("收到移动位置消息");

        }

    }

    /***
     * 处理目录Notify
     */
    @SneakyThrows
    private void processNotifyCatalog(RequestEvent event){

        FromHeader fromHeader = (FromHeader) event.getRequest().getHeader(FromHeader.NAME);
        String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);

        Device device = SipProcessorContext.deviceMap.get(deviceId);
        if (device == null) {
            log.warn("[收到目录订阅], 但是设备已经离线");
            return;
        }
        Element rootElement = getRootElement(event, "gb2312");
        if (rootElement == null) {
            log.warn("[ 收到目录订阅 ] content cannot be null, {}", event.getRequest());
            return;
        }
        Element deviceListElement = rootElement.element("DeviceList");
        if (deviceListElement == null) {
            log.warn("[ 收到目录订阅 ] content cannot be null, {}", event.getRequest());
            return;
        }
        Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
        if (deviceListIterator != null) {

            // 遍历DeviceList
            while (deviceListIterator.hasNext()) {
                Element itemDevice = deviceListIterator.next();
                Element eventElement = itemDevice.element("Event");
                log.info("[收到Notify-Catalog]：Event = {}", eventElement.getText());

                DeviceChannel deviceChannel;
                if (CatalogEvent.ADD.getValue().equalsIgnoreCase(eventElement.getText()) ||
                        CatalogEvent.UPDATE.getValue().equalsIgnoreCase(eventElement.getText())) {

                    deviceChannel = DeviceChannel.decode(itemDevice);

                }else {
                    deviceChannel = DeviceChannel.decodeWithOnlyDeviceId(itemDevice);
                }

                deviceChannel.setDeviceId(deviceId);
                log.info("[收到Notify-Catalog]：DeviceChannel = {}", deviceChannel);

                // todo

            }
        }

    }

    /***
     * 处理alarm设备报警Notify
     */
    @SneakyThrows
    private void processNotifyAlarm(RequestEvent event) {

        if (!sipConfig.isAlarm()) {
            return;
        }

        FromHeader fromHeader = (FromHeader) event.getRequest().getHeader(FromHeader.NAME);
        String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader);

        Element rootElement = getRootElement(event, "gb2312");
        if (rootElement == null) {
            log.error("处理alarm设备报警Notify时未获取到消息体{}", event.getRequest());
            return;
        }
        Element deviceIdElement = rootElement.element("DeviceID");
        String channelId = deviceIdElement.getText();

        Device device = SipProcessorContext.deviceMap.get(deviceId);
        if (device == null) {
            log.warn("[ NotifyAlarm ] 未找到设备：{}", deviceId);
            return;
        }

        DeviceAlarm deviceAlarm = new DeviceAlarm();
        deviceAlarm.setDeviceId(deviceId);
        deviceAlarm.setDeviceName(device.getName());
        deviceAlarm.setAlarmPriority(XmlUtil.getText(rootElement, "AlarmPriority"));
        deviceAlarm.setAlarmMethod(XmlUtil.getText(rootElement, "AlarmMethod"));
        String alarmTime = XmlUtil.getText(rootElement, "AlarmTime");
        if (alarmTime == null) {
            log.warn("[ NotifyAlarm ] AlarmTime cannot be null");
            return;
        }
        deviceAlarm.setAlarmTime(alarmTime);
        if (XmlUtil.getText(rootElement, "AlarmDescription") == null) {
            deviceAlarm.setAlarmDescription("");
        } else {
            deviceAlarm.setAlarmDescription(XmlUtil.getText(rootElement, "AlarmDescription"));
        }
        if (NumberUtil.isDouble(XmlUtil.getText(rootElement, "Longitude"))) {
            deviceAlarm.setLongitude(Double.parseDouble(XmlUtil.getText(rootElement, "Longitude")));
        } else {
            deviceAlarm.setLongitude(0.00);
        }
        if (NumberUtil.isDouble(XmlUtil.getText(rootElement, "Latitude"))) {
            deviceAlarm.setLatitude(Double.parseDouble(XmlUtil.getText(rootElement, "Latitude")));
        } else {
            deviceAlarm.setLatitude(0.00);
        }

        log.info("[收到Notify-Alarm]：{}/{}", device.getDeviceId(), deviceAlarm.getChannelId());

        // todo




    }
}
